#ifndef COLLISIONHUL_H_
#define COLLISIONHUL_H_
#define DEBUG_
#include <map>
#include <list>
#include "math/Vector3.h"
#include "math/Matrix3.h"

/*
*	___ COLLISIONHUL Header___
* 
*
***************************************************************/



class EdgeInfo
{
	public:
		EdgeInfo(Vector3* normal, bool isSmooth )
		{
			_nOriginal = NULL;
			if( normal != NULL )
			{
				_normal = *normal;
				_nOriginal = normal;
			}
			_isSmooth = isSmooth;
		}
		
		void transform( const Matrix3& mat )
		{
			if( _nOriginal )
				_normal = mat.MultNormal( *_nOriginal);
		}
		
		Vector3 _normal;
		Vector3* _nOriginal;
		bool _isSmooth;
};

class TrianglePlane 
{
	private:
		Vector3*	_p1, *_p2, *_p3, *_n,*_nOriginal, *_edgeP1, *_edgeP2, *_edgeP3;
		EdgeInfo *_edge1, *_edge2, *_edge3;
		float _d;
	public:
		TrianglePlane(Vector3* p1,Vector3* p2,Vector3* p3, Vector3* normal, EdgeInfo* edge1, EdgeInfo* edge2, EdgeInfo* edge3) 
		{ 
			_p1 = p1; 
			_p2 = p2; 
			_p3 = p3; 
			_edge1 = edge1;
			_edge2 = edge2;
			_edge3 = edge3;
			_nOriginal = normal;
			_n = new Vector3( *normal ); 
			_edgeP1 = new Vector3( (*_p2) - (*_p1) );
			_edgeP2 = new Vector3( (*_p3) - (*_p2) );
			_edgeP3 = new Vector3( (*_p1) - (*_p3) );
#ifdef DEBUG			
			cout <<"==] CONSTRCTOR_TRIANGLE_PLANE:NORMAL ["<<*_n<<"]"<<endl;
			cout <<"==] CONSTRCTOR_TRIANGLE_PLANE:EDGE1 ["<<*_edgeP1<<"]"<<endl;
			cout <<"==] CONSTRCTOR_TRIANGLE_PLANE:NORMAL ["<<*_edgeP2<<"]"<<endl;
			cout <<"==] CONSTRCTOR_TRIANGLE_PLANE:NORMAL ["<<*_edgeP3<<"]"<<endl;
#endif			
			computeHessDistance();
		}
		
		~TrianglePlane( ) { delete _p1; delete _p2; delete _p3; delete _n;delete _edge1;delete _edge2;delete _edge3; }
		Vector3& getP1() const { return *_p1; }
		Vector3& getP2() const { return *_p2; 	}
		Vector3& getP3() const { return *_p3; }
		Vector3& getEdgeRayP1() const { return *_edgeP1; }
		Vector3& getEdgeRayP2() const { return *_edgeP2; }
		Vector3& getEdgeRayP3() const { return *_edgeP3; }
		EdgeInfo& getEdge1() const { return *_edge1; }
		EdgeInfo& getEdge2() const { return *_edge2; }
		EdgeInfo& getEdge3() const { return *_edge3; }		
		Vector3& getNormal() const { return *_n; }
		float getDistance() const{ return _d; }
		void setP1(const Vector3& p1 ) { *_p1 = p1; }
		void setP2(const Vector3& p2 ) { *_p2 = p2; }
		void setP3(const Vector3& p3 ) { *_p3 = p3; }
		void setNormal(const Vector3& n ) { *_n = n; }
		void computeHessDistance()
		{
			_d = (*_p1) * (*_n);
		}
		void transform( const Matrix3& transMat )
		{
			*_edgeP1 = ((*_p2)-(*_p1));
			*_edgeP2 = ((*_p3)-(*_p2));
			*_edgeP3 = ((*_p1)-(*_p3));
			
			*_n = transMat.MultNormal(*_nOriginal);			
			
			_edge1->transform( transMat );
			_edge2->transform( transMat );
			_edge3->transform( transMat );

#ifdef DEBUG			
			cout <<"==] TRANSFORM_TRIANGLE_PLANE:NORMAL ["<<*_n<<"]"<<endl;
#endif			
			computeHessDistance();
		}
};

 
class CollisionHul
{
	private:		
		map<int,CollisionHul*> _childHuls;
		Vector3								*_center;
		float								*_radius;		
	public:
		CollisionHul( );
		~CollisionHul( );

		void ComputeHul();

		virtual void setTransformation( const Matrix3& mat );
		virtual list<TrianglePlane*>* getTrianglePlaneList( ) = 0;
		
		void addChildHul( int id, CollisionHul* childHul ); 
		void removeChildHul( int id );
		map<int,CollisionHul*>* getChildHuls( );

		Vector3 getCenter( );
		float getRadius( );
		
		
};

/***************************************************************/
#endif
